package tjs.study.notes.dotest.disruptor.parallel.spring;

import com.lmax.disruptor.WorkProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;

import java.util.concurrent.ArrayBlockingQueue;

public class RunDisruptorApplication extends tjs.study.notes.dotest.TjsStudyNotesApplication implements CommandLineRunner {
    /**
     * 单生产者，多消费者
     * 发送者：
     * 1. 通过CAS，获取自增的序列号
     * {@link com.lmax.disruptor.MultiProducerSequencer#next(int)}
     * 2. 序列号与预热的数组.length 求膜(移位运算)，获取目标载体
     * {@link RingBufferFields#elementAt(long)}
     * 3. 调用目标载体，setXXX
     * <p>
     * 消费者：
     * {@link WorkProcessor#run()}
     * 1. 先通过CAS获取一个已消费的序列号A （workSequence.compareAndSet）
     * 2. 比较生产者当前最大序列号是否小于已消费的序列号A（ cachedAvailableSequence = sequenceBarrier.waitFor(nextSequence);），
     * 3. 小于则执行消费，大于则执行等待策略（workHandler.onEvent(event);）
     * <p>
     * 区别：
     * 1. 使用预热模式。不存在元素的删除操作，只有覆盖，所以没有gc。（但是消费后注意是否手动清除，否则可能OOM）
     * 2. 属性填充：通过添加额外的无用信息，避免伪共享问题(不相干的数据放在同一个缓存行，cpu发生竞争，导致缓存行失效，去主内存再次查回数据-耗性能)
     * 3. 环形数组：数组-连续内存，cpu可一次加载多个载体。相比于线性队列，无需同步head和tail头尾指针
     * 4. CAS无锁方式控制生产、消费进度。。相比于线性队列，CAS自旋一定时间会休眠，减少CPU的使用
     *
     * @param args
     */
    public static void main(String[] args) {
        // ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(10);
        // arrayBlockingQueue.poll()
        SpringApplication.run(RunDisruptorApplication.class, args);
    }

    @Autowired
    private DisruptorProducer disruptorProducer;

    @Override
    public void run(String... args) throws Exception {
        for (int i = 0; i < 100; i++) {
            disruptorProducer.sendJson("aaaa");
        }
    }
}
